<template>
  <el-tree
    ref="tree"
    class="ui-tree"
    :class="['ui-tree--' + type]"
    :data="innerData"
    :show-checkbox="multiple"
    :load="handleLoadNodes"
    :node-key="nodeKey"
    :current-node-key="currentKey"
    :check-strictly="checkStrictly"
    :default-expand-alll="defaultExpandAll"
    :default-expanded-keys="defaultExpandedKeys"
    :highlight-current="highlightCurrent"
    :expand-on-click-node="expandOnClickNode"
    :default-checked-keys="defaultCheckedKeys"
    :lazy="lazy"
    :props="treeProps"
    @current-change="handleCurrentChange"
    @check-change="handleCheckChange"
  >
    <template slot-scope="scope">
      <slot v-bind="scope">
        {{ scope.data[labelField] }}
      </slot>
    </template>
  </el-tree>
</template>
<script>
import Tree from 'element-ui/lib/tree'
import 'element-ui/lib/theme-chalk/tree.css'
import { getNodesByLevel } from './utils'

export default {
  name: 'UiTree',
  components: {
    ElTree: Tree
  },
  props: {
    value: {
      type: [String, Number, Array]
    },
    type: {
      type: String,
      default: 'default',
      validator (value) {
        return ['compact', 'default'].includes(value)
      }
    },
    data: {
      type: Array
    },
    multiple: {
      type: Boolean
    },
    nodeKey: {
      type: String,
      default: 'id'
    },
    checkStrictly: {
      type: Boolean,
      default: false
    },
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    highlightCurrent: {
      type: Boolean,
      default: false
    },
    expandOnClickNode: {
      type: Boolean,
      default: false
    },
    lazy: {
      type: Boolean,
      default: false
    },
    labelField: {
      type: String,
      default: 'text'
    },
    childrenField: {
      type: String,
      default: 'children'
    },
    checkLeafMethod: {
      type: Function
    },
    queryMethod: {
      type: Function
    },
    defaultExpandedLevel: {
      type: Number
    }
  },
  computed: {
    treeProps() {
      return {
        label: this.labelField,
        children: this.childrenField,
        isLeaf: this.checkLeafMethod
      }
    },
    defaultExpandedKeys() {
      return getNodesByLevel(this.innerData, this.defaultExpandedLevel).map(v => {
        return v[this.nodeKey]
      })
    },
    defaultCheckedKeys() {
      if (this.multiple) {
        return this.value || []
      }
      return []
    },
    currentKey() {
      if (this.multiple) {
        return
      }
      return this.value
    }
  },
  data() {
    return {
      innerData: this.data
    }
  },
  watch: {
    data() {
      this.innerData = this.data
    },
    currentKey() {
      this.handleCurrentValueChange()
    },
    value() {
      if (this.multiple) {
        this.$refs.tree && this.$refs.tree.setCheckedKeys(this.value || [])
      }
    }
  },
  created() {
    if (!this.lazy) {
      if (this.queryMethod) {
        this.queryMethod().then(rs => {
          this.innerData = rs
        })
      }
    }
  },
  methods: {
    handleLoadNodes(root, callback) {
      if (this.queryMethod) {
        this.queryMethod({
          parentNode: root
        }).then(rs => {
          callback(rs)
        }, () => {
          callback([])
        })
      }
    },
    handleCurrentChange(evt) {
      this.$emit('current-change', evt)
      if (!this.multiple) {
        this.$emit('input', evt[this.nodeKey])
      }
    },
    getCheckedNodes() {
      return this.$refs.tree.getCheckedNodes()
    },
    handleCurrentValueChange() {
      if (this.$refs.tree) {
        if ((this.currentKey === null || this.currentKey === undefined || this.currentKey === '')) {
          this.$refs.tree.setCurrentKey(null)
        } else {
          this.$refs.tree.setCurrentKey(this.currentKey)
        }
      }
    },
    handleCheckChange(evt) {
      this.$emit('input', this.$refs.tree.getCheckedKeys())
    }
  }
}
</script>

<style lang="less">
.ui-tree.el-tree {
  background-color: transparent;
  .el-tree-node{
    margin-bottom: 0;
  }
  .el-tree-node__content{
    height: auto;
    line-height: 24px;
    padding-top: 5px;
    padding-bottom: 5px;
    border-radius: 4px;
    transition: all .25s;
    display: flex;
    flex-direction: row;
    align-items: center;
    &:hover{
      color: #40404E;
    }
  }
  .el-tree-node__children{
    animation: none!important;
    transition: none!important;
  }
  .el-tree-node__expand-icon{
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 1px solid transparent;
    border-radius: 3px;
    padding: 0;
    transition: none;
    margin-right: 6px;
    &:not(.is-leaf) {
      background-color: #fff;
      position: relative;
      border-color: #ccc;
      &:after, &:before{
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background-color: #aaa;
      }
      &.expanded{
        &:after {
          display: none;
        }
        &:before {
          width: 1px;
          height: 8px;
        }
      }
      &:not(.expanded) {
        &:after {
          width: 8px;
          height: 1px;
        }
        &:before {
          width: 1px;
          height: 8px;
        }
      }
    }
  }
  &.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{
    background-color: #e2ebfe;
    color: #3385FF;
    font-weight: bold;
  }
  &.ui-tree--compact{
    .el-tree-node__content{
      border-radius: 0;
      &:before {
        content: '';
        display: inline-block;
        width: 18px;
        height: 1px;
      }
    }
  }
}
</style>
